package com.skillworld.webapp.model.itemservice;

import java.sql.Connection;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;

import com.skillworld.webapp.model.bag.ItemRecord;
import com.skillworld.webapp.model.bag.ItemRecordDao;
import com.skillworld.webapp.model.item.Item;
import com.skillworld.webapp.model.item.ItemDao;
import com.skillworld.webapp.model.user.User;
import com.skillworld.webapp.model.user.UserDao;
import com.skillworld.webapp.model.util.InvalidArgumentException;

import es.udc.pojo.modelutil.exceptions.InstanceNotFoundException;


@Service("ItemService")
@Transactional
public class ItemServiceImpl implements ItemService{

    @Autowired
    private UserDao userDao;
    
    @Autowired
    private ItemRecordDao itemRecordDao;
    
    @Autowired
    private ItemDao itemDao;
    

    @Transactional(readOnly=true)
    public Item findItem(Long itemId) throws InstanceNotFoundException
    {
        return itemDao.findById(itemId);
    }
    
    @Transactional(isolation=Isolation.REPEATABLE_READ)
	public ItemRecord buyItem(Long userId, Long itemId)
	        throws InstanceNotFoundException, NoLevelException,
	                BagFullException
	{
		User user = userDao.findById(userId);
		Item item = itemDao.findById(itemId);

        if(item.isBlockedFor(user))
        { throw new NoLevelException(userId); }

		if (user.getBag().isFull())
		{ throw new BagFullException(userId); }
		
		return user.getBag().addItem(item);
	}
	
	public void removeItemRecord(long userId, long recordId)
	        throws InstanceNotFoundException
	{
	    User user = userDao.findById(userId); 
	    ItemRecord bagEntry = itemRecordDao.findById(recordId);
	    
	    if(!user.getBag().getEntries().contains(bagEntry))
	    { throw new InstanceNotFoundException(recordId, ItemRecord.class.getName()); }
	    
	    user.getBag().removeEntry(bagEntry);
	}
	
	@Transactional(readOnly=true)
	public List<Item> visitStore()
	{ 
		return itemDao.findAll();
	}

	/*
	 * DEPRECATED: Use Item.isBlockedFor(User) instead
	 */
/*	public boolean viewBlockedUserItem(Long userId, Long itemId)throws InstanceNotFoundException
	{
	    User user = userDao.findById(userId);
        Item item = this.itemDao.findById(itemId);
        boolean resp = true;
	    
        For this version, we only considerate the global lever.
        if(user.getGlobalLevel() >= item.getLockLevel())
        { resp = false; }
        
	    return resp;
	}*/
	
	
	public void giftItem(long giverId, long recipientId, long entryId)
	        throws InvalidArgumentException, InstanceNotFoundException, BagFullException
	{	
	    if(giverId == recipientId)
	    { throw new InvalidArgumentException(); }
	       
		User giver = userDao.findById(giverId);	
		User recipient = userDao.findById(recipientId);
		
	    if (recipient.getBag().isFull())
	    { throw new BagFullException(recipientId); }
	    
	    ItemRecord entry = itemRecordDao.findById(entryId);
	    
	    if (!giver.getBag().getEntries().contains(entry))
        { throw new InstanceNotFoundException(entryId, ItemRecord.class.getName()); }

	    recipient.getBag().copyEntry(entry);
	    giver.getBag().removeEntry(entry);	
	}
	
	
	/*
	 * DEPRECATED: Use User.getBag().getItemEntries(Item) instead
	 */
/*	public List<ItemRecord> getUserItemRecords(Long userId, Long itemId) throws InstanceNotFoundException
	{
	    User user = userDao.findById(userId);
	    Bag userInv = null;
	    Item item = null;
	    ItemRecord irExample = null;
	    //
	    
	    userInv = user.getBag();
	    item = this.itemDao.findById(itemId);
	    
	    
	    irExample = new ItemRecord(item, userInv);
	    
	    List<ItemRecord> l= this.itemRecordDao.findByExample(irExample); 
	    return l;
	}*/
	
	/*
	 * DEPRECATED: Use User.getBag().getEntries().contains(itemRecord) instead
	 */
/*	public boolean hasInventoryItemRecord(Long idInventory, Long idItemRecord) throws InstanceNotFoundException
	{
	    boolean resp = false;
	    Bag inv = null;
	    ItemRecord ir = null;
	    //
	    
	    inv = this.bagDao.findById(idInventory);
	    ir = this.itemRecordDao.findById(idItemRecord);
	    
	    resp = inv.getEntries().contains(ir);
	    return resp;
	}*/
	
	/*
	 * DEPRECATED: Use User.getBag().hasItem(Item) instead
	 */
	/*public boolean hasUserItem(Long userId, Long itemId) throws InstanceNotFoundException
    {
        boolean resp = false;
        User user = null;
        Item item = null;
        
        //
        
        user = this.userDao.findById(userId);
        item = this.itemDao.findById(itemId);
        
        List<ItemRecord> rec_list = this.itemRecordDao.findByInventoryAndItem(user.getBag().getInventoryId(), item.getItemId());
        //ItemRecord rec = new ItemRecord(item, user.getBag());
        //List<ItemRecord> rec_list = this.itemRecordDao.findByExample(rec);       
        
        if(rec_list!=null)
        {resp=(rec_list.size()>0)?true:false; }

        return resp;
    }*/
	
	/*
	 * DEPRECATED: Use User.getBag().consumeItem(Item) instead
	 */
/*	public void consumeItem(Long userId, Long itemId) throws InstanceNotFoundException, NoUsagesLeftException
	{
	    List<ItemRecord> ir_lst = null;
	    User u = null;
	    Item item = null;
	    boolean flag_ok = false;
	    Iterator<ItemRecord> i = null;
	    ItemRecord rec =  null;
	    //
	    
	    u = this.userDao.findById(userId);
	    item = this.itemDao.findById(itemId);
	    
	    ir_lst = this.itemRecordDao.findByInventoryAndItem(u.getBag().getInventoryId(), item.getItemId());
	    i = ir_lst.iterator();
	    
	    while(i.hasNext() && (flag_ok != true))
	    {
	        rec = i.next();
	        if(Calendar.getInstance().before(rec.getExpirationDate()))
	        { u.getBag().removeEntry(rec); }
	        else
	        { 
	            if(rec.getUsesLeft()<=0)
	            { u.getBag().removeEntry(rec); }
	            else
	            {
	                flag_ok = true;
	                rec.consume();
	                if((rec.getUsesLeft()<=0))
	                { u.getBag().removeEntry(rec); }
                }
	        }
	    }
	    if (flag_ok != true)
	    { throw new NoUsagesLeftException(item.getItemId()); }	    
	}*/
	
}
